#ifndef BASE_API_H_
#define BASE_API_H_

#include <stdint.h>
#include <stdio.h>
#include <error.h>

// #define USE_FULL_ASSERT

// #define USE_DEBUG

#ifdef USE_DEBUG
#define DEBUG_LINE() printf("[%s:%s] line=%d \n",__FILE__, __func__, __LINE__)
#define DEBUG_ERR(fmt, args...) printf("[%s:%d] "#fmt" errno=%d, %m \n", __func__, __LINE__, ##args, errno)
#define DEBUG_INFO(fmt, args...) printf("[%s:%d] "#fmt" \n", __func__, __LINE__, ##args)
#else
#define DEBUG_LINE()
#define DEBUG_ERR(fmt, ...)
#define DEBUG_INFO(fmt, ...)
#endif


#define BASE_ADDR 0xA0000000
#define ADDRESS_RANGE 0x1000

#define PULSE_UNIT_TIME 100  # ns

#define REG0_ADDR 0
#define REG1_ADDR (1 * 4)
#define REG2_ADDR (2 * 4)
#define REG3_ADDR (3 * 4)
#define REG4_ADDR (4 * 4)
#define REG5_ADDR (5 * 4)
#define REG6_ADDR (6 * 4)
#define REG7_ADDR (7 * 4)
#define REG8_ADDR (8 * 4)
#define REG9_ADDR (9 * 4)
#define REG10_ADDR (10 * 4)
#define REG11_ADDR (11 * 4)
#define REG12_ADDR (12 * 4)
#define REG13_ADDR (13 * 4)
#define REG14_ADDR (14 * 4)
#define REG15_ADDR (15 * 4)
#define REG16_ADDR (16 * 4)
#define REG51_ADDR (51 * 4)
#define REG52_ADDR (52 * 4)
#define REG55_ADDR (55 * 4)
#define REG56_ADDR (56 * 4)
#define REG57_ADDR (57 * 4)
#define REG58_ADDR (58 * 4)
#define REG59_ADDR (59 * 4)
#define REG65_ADDR (65 * 4)
#define REG66_ADDR (66 * 4)
#define REG67_ADDR (67 * 4)
#define REG75_ADDR (75 * 4)
#define REG76_ADDR (76 * 4)
#define REG77_ADDR (77 * 4)
#define REG80_ADDR (80 * 4)

#define TOTAL_ROW 1152
#define TOTAL_CHANNEL 8
#define ONE_CHANNEL_ROW 144
#define TOTAL_COL 128

#define OP_CFG_DAC 1
#define OP_CALC 2
#define OP_FORM 3
#define OP_SET 4
#define OP_RESET 5
#define OP_READ 6
#define OP_SELECT_CHIP 9
#define OP_CFG_CSN 0x0A
#define OP_POWER_ON 0x0F
#define OP_POWER_OFF 0x1F

#define POS_DIR 1
#define NEG_DIR 2

#ifdef USE_FULL_ASSERT

/****
    * @brief  The assert_param macro is used for function's parameters check.
    * @param  expr: If expr is false, it calls assert_failed function which reports
    *         the name of the source file and the source line number of the call
    *         that failed. If expr is true, it returns no value.
    * @retval None
    */
    #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
    void assert_failed(uint8_t* file, uint32_t line);
#else
    #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */

typedef struct
{
    uint32_t regAddr;
    uint32_t selectedBitMap;
    uint32_t actualBitMap;
} DIN_t;

uint32_t ReadReg(uint32_t OffsetAddr);
int OpenMMIO(void);
int CloseMMIO(void);
int PowerOn(void);
int PowerOff(void);
int SelectChip(uint32_t ChipNum);
void DevInit(void);
uint32_t ReadOneCell_1(uint32_t rowIdx, uint32_t colIdx);
void CalcArray(int8_t *rowInput, uint32_t colStart, uint32_t colCount, uint8_t *output);
int CalcArray_1(int8_t *rowInput, uint32_t rowStart, uint32_t rowCount, uint32_t colStart, uint32_t colCount, uint8_t *output);
int CalcArray_2(int8_t *rowInput, uint32_t rowStart, uint32_t rowCount, uint32_t colStart, uint32_t colCount, uint8_t *output, uint32_t calcCount);

#endif